package com.cloudesire.tisana4j.test;
import com.cloudesire.tisana4j.ExceptionTranslator;
import com.cloudesire.tisana4j.RestClient;
import com.cloudesire.tisana4j.RestClientFactory;
import com.cloudesire.tisana4j.exceptions.AccessDeniedException;
import com.cloudesire.tisana4j.exceptions.BadRequestException;
import com.cloudesire.tisana4j.exceptions.InternalServerErrorException;
import com.cloudesire.tisana4j.exceptions.ResourceNotFoundException;
import com.cloudesire.tisana4j.exceptions.RestException;
import com.cloudesire.tisana4j.exceptions.UnprocessableEntityException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class MockedServerTest
{
private final static Logger log = LoggerFactory.getLogger( MockedServerTest.class );
private final RestClient client = RestClientFactory.getDefaultClient();
private MockWebServer server;
private String serverUrl = "";
@Before
public void setUp() throws Exception
{
server = new MockWebServer();
}
@Test
public void testGetData() throws Exception
{
String data = "ColumnA,ColumnB,ColumnC\r\nA,B,c\r\n,a,b,c\r\n";
MockResponse response = new MockResponse();
response.setResponseCode( 200 );
response.addHeader( "Content-Type", "text/csv" );
response.setBody( data );
server.enqueue( response );
server.start( 9999 );
InputStream stream = client.getData( server.getUrl( "/get/csv" ), null );
byte[] b = new byte[1024];
int r = stream.read( b );
assertTrue( r > 0 );
String out = new String( b );
String[] lines = out.split( "\r\n" );
assertEquals( 4, lines.length );
}
@Test
public void testDelete() throws Exception
{
MockResponse response = new MockResponse();
response.setResponseCode( 204 );
server.enqueue( response );
server.start( 9999 );
client.delete( server.getUrl( "/delete/15" ) );
RecordedRequest request = server.takeRequest();
assertEquals( "/delete/15", request.getPath() );
assertEquals( "DELETE", request.getMethod() );
}
@Test
public void testPatch() throws Exception
{
MockResponse response = new MockResponse();
response.setResponseCode( 204 );
server.enqueue( response );
server.start( 9999 );
Map<String, String> map = new HashMap<>();
map.put( "action", "doThings" );
client.patch( server.getUrl( "/patch/15" ), map );
RecordedRequest request = server.takeRequest();
assertEquals( "/patch/15", request.getPath() );
assertEquals( "PATCH", request.getMethod() );
assertTrue( request.getBody().size() > 0 );
assertTrue( request.getBody().readUtf8().contains( "{\"action\":\"doThings\"}" ) );
}
@Test
public void testGet() throws Exception
{
final int resourceId = 15;
String json = "{ \"id\": " + resourceId + " }";
MockResponse response = new MockResponse();
response.setResponseCode( 200 );
response.addHeader( "Content-Type", "application/json" );
response.setBody( json );
server.enqueue( response );
server.start( 9999 );
Resource resource = client.get( server.getUrl( "/resource/" + resourceId ), Resource.class );
RecordedRequest request = server.takeRequest();
assertEquals( "/resource/" + resourceId, request.getPath() );
assertEquals( "GET", request.getMethod() );
assertEquals( 0, request.getBody().size() );
assertNotNull( resource.getId() );
assertTrue( resource.getId().equals( resourceId ) );
}
@Test
public void testGetRaw() throws Exception
{
final int resourceId = 15;
String json = "{ \"id\": " + resourceId + " }";
MockResponse response = new MockResponse();
response.setResponseCode( 200 );
response.addHeader( "Content-Type", "application/json" );
response.setBody( json );
server.enqueue( response );
server.start( 9999 );
InputStream inputStream = client.get( server.getUrl( "/resource/" + resourceId ) );
RecordedRequest request = server.takeRequest();
assertEquals( "/resource/" + resourceId, request.getPath() );
assertEquals( "GET", request.getMethod() );
assertEquals( 0, request.getBody().size() );
assertNotNull( response );
String s = IOUtils.toString( inputStream, StandardCharsets.UTF_8.toString() );
assertNotNull( s );
assertEquals( "{ \"id\": 15 }", s );
}
@Test
public void testGetCollection() throws Exception
{
String json = "[{ \"id\": 15 }]";
MockResponse response = new MockResponse();
response.setResponseCode( 200 );
response.addHeader( "Content-Type", "application/json" );
response.setBody( json );
server.enqueue( response );
server.start( 9999 );
List<Resource> collection = client.getCollection( server.getUrl( "/resources" ), Resource.class );
RecordedRequest request = server.takeRequest();
assertEquals( "/resources", request.getPath() );
assertEquals( "GET", request.getMethod() );
assertEquals( 0, request.getBody().size() );
assertFalse( collection.isEmpty() );
assertEquals( "15", collection.get( 0 ).id.toString() );
}
@Test
public void testGetCollectionWithTypeReference() throws Exception
{
String json = "[ 1.50 ]";
MockResponse response = new MockResponse();
response.setResponseCode( 200 );
response.addHeader( "Content-Type", "application/json" );
response.setBody( json );
server.enqueue( response );
server.start( 9999 );
List<BigDecimal> collection = client.get( server.getUrl( "/resources" ), new TypeReference<List<BigDecimal>>(){} );
RecordedRequest request = server.takeRequest();
assertEquals( "/resources", request.getPath() );
assertEquals( "GET", request.getMethod() );
assertEquals( 0, request.getBody().size() );
assertFalse( collection.isEmpty() );
assertEquals( "1.50", collection.get( 0 ).toString() );
}
@Test
public void testPost() throws Exception
{
final int resourceId = 15;
String json = "{ \"id\": " + resourceId + " }";
MockResponse response = new MockResponse();
response.setResponseCode( 201 );
response.addHeader( "Content-Type", "application/json" );
response.setBody( json );
server.enqueue( response );
server.start( 9999 );
Resource resource = new Resource();
resource.setId( resourceId );
Resource postResponse = client.post( server.getUrl( "/create" ), resource );
RecordedRequest request = server.takeRequest();
assertEquals( "/create", request.getPath() );
assertEquals( "POST", request.getMethod() );
assertTrue( request.getBody().size() > 0 );
assertNotNull( postResponse.getId() );
assertEquals( resourceId, postResponse.getId().intValue() );
}
@Test
public void testEmptyPostEmptyResponse() throws Exception
{
MockResponse response = new MockResponse();
response.setResponseCode( 201 );
server.enqueue( response );
server.start( 9999 );
Resource postResponse = client.post( server.getUrl( "/create" ), null, null, null );
RecordedRequest request = server.takeRequest();
assertEquals( 0, request.getBody().size() );
assertEquals( "/create", request.getPath() );
assertEquals( "POST", request.getMethod() );
assertNull( postResponse );
}
@Test
public void testPut() throws Exception
{
final int resourceId = 15;
String json = "{ \"id\": " + resourceId + " }";
MockResponse response = new MockResponse();
response.setResponseCode( 200 );
response.addHeader( "Content-Type", "application/json" );
response.setBody( json );
server.enqueue( response );
server.start( 9999 );
Resource resource = new Resource();
resource.setId( resourceId );
Resource putResponse = client.put( server.getUrl( "/update/" + resourceId ), resource );
RecordedRequest request = server.takeRequest();
assertTrue( request.getBody().size() > 0 );
assertEquals( "/update/" + resourceId, request.getPath() );
assertEquals( "PUT", request.getMethod() );
assertNotNull( putResponse.getId() );
assertTrue( putResponse.getId().equals( resourceId ) );
}
@Test
public void testInternalServerError() throws Exception
{
String json = "{ \"error\": \"Customized Internal Server Error\" }";
MockResponse response = new MockResponse();
response.setResponseCode( 500 );
response.addHeader( "Content-Type", "application/json" );
response.setBody( json );
server.enqueue( response );
server.start( 9999 );
try
{
client.get( server.getUrl( "/fail/500" ), Resource.class );
fail();
}
catch ( Exception e )
{
if ( !( e instanceof InternalServerErrorException ) ) fail();
RestException re = (RestException) e;
assertEquals( 500, re.getResponseCode() );
assertEquals( "{ \"error\": \"Customized Internal Server Error\" }", re.getMessage() );
}
}
@Test
public void testBadRequestError() throws Exception
{
MockResponse response = new MockResponse();
response.setResponseCode( 400 );
server.enqueue( response );
server.start( 9999 );
try
{
client.get( server.getUrl( "/fail/400" ), Resource.class );
fail();
}
catch ( Exception e )
{
if ( !( e instanceof BadRequestException ) ) fail();
}
}
@Test
public void testAccessDeniedError() throws Exception
{
MockResponse response = new MockResponse();
response.setResponseCode( 403 );
server.enqueue( response );
server.start( 9999 );
try
{
client.get( server.getUrl( "/fail/403" ), Resource.class );
fail();
}
catch ( Exception e )
{
if ( !( e instanceof AccessDeniedException ) ) fail();
}
}
@Test
public void testResourceNotFoundError() throws Exception
{
MockResponse response = new MockResponse();
response.setResponseCode( 404 );
server.enqueue( response );
server.start( 9999 );
try
{
client.get( server.getUrl( "/fail/404" ), Resource.class );
fail();
}
catch ( Exception e )
{
if ( !( e instanceof ResourceNotFoundException ) ) fail();
}
}
@Test
public void testUnprocessableEntityError() throws Exception
{
MockResponse response = new MockResponse();
response.setResponseCode( 422 );
server.enqueue( response );
server.start( 9999 );
try
{
client.get( server.getUrl( "/fail/422" ), Resource.class );
fail();
}
catch ( Exception e )
{
if ( !( e instanceof UnprocessableEntityException ) ) fail();
}
}
@Test
public void testTranslateError() throws Exception
{
String json = "{ \"error\": \"Customized Internal Server Error\" }";
MockResponse response = new MockResponse();
response.setResponseCode( 500 );
response.addHeader( "Content-Type", "application/json" );
response.setBody( json );
server.enqueue( response );
server.start( 9999 );
RestClient client2 = new RestClient( true );
client2.setExceptionTranslator( new TestExceptionTranslator() );
try
{
client2.get( server.getUrl( "/fail/500" ), Resource.class );
fail();
}
catch ( Exception e )
{
if ( !( e instanceof RestException ) ) fail();
RestException re = (RestException) e;
assertEquals( 500, re.getResponseCode() );
assertEquals( "Customized Internal Server Error", re.getMessage() );
}
}
@Test
public void testTranslateError2() throws Exception
{
String json = "{ \"error\": \"Customized Bad Request\" }";
MockResponse response = new MockResponse();
response.setResponseCode( 400 );
response.addHeader( "Content-Type", "application/json" );
response.setBody( json );
server.enqueue( response );
server.start( 9999 );
RestClient client2 = new RestClient( true );
client2.setExceptionTranslator( new TestExceptionTranslator() );
try
{
client2.get( server.getUrl( "/fail/400" ), Resource.class );
fail();
}
catch ( Exception e )
{
if ( !( e instanceof BadRequestException ) ) fail();
BadRequestException bre = (BadRequestException) e;
assertEquals( 400, bre.getResponseCode() );
assertEquals( "Customized Bad Request", bre.getMessage() );
}
}
@After
public void tearDown() throws Exception
{
try
{
server.shutdown();
}
catch ( IllegalStateException e )
{
log.info( "Mock server not started" );
}
}
public static class Resource
{
private Integer id;
public Integer getId()
{
return id;
}
public void setId( Integer id )
{
this.id = id;
}
}
public static class TestExceptionTranslator implements ExceptionTranslator
{
@SuppressWarnings ( "unchecked" )
@Override
public RestException translateException( int responseCode, String responseMessage, String errorStream,
ResponseMessage returnMessageRef, Header[] headers )
{
if ( responseCode == 400 )
{
returnMessageRef.setResponse( "Customized Bad Request" );
return null;
}
if ( responseCode != 500 ) return null;
ObjectMapper mapper = new ObjectMapper();
try
{
ErrorDto obj = mapper.reader( ErrorDto.class ).readValue( errorStream );
return new RestException( responseCode, obj.getError() );
}
catch ( Exception e )
{
return null;
}
}
}
public static class ErrorDto
{
private String error;
public ErrorDto()
{
}
public ErrorDto( String errorMsg )
{
this.error = errorMsg;
}
public String getError()
{
return error;
}
public void setError( String errorMsg )
{
this.error = errorMsg;
}
}
}